package com.ip.user.service.impl;

import com.alibaba.fastjson.JSON;
import com.ip.common.utils.ValidateUtils;
import com.ip.db.utils.RedisUtil;
import com.ip.user.models.dto.EmailCaptchaDTO;
import com.ip.user.models.service.EmailCaptchaService;
import com.ip.user.models.service.SysUserService;
import com.ip.user.models.vo.UserVO;
import org.apache.dubbo.config.annotation.DubboService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * 邮箱验证码服务实现类
 */
@DubboService
@Service
public class EmailCaptchaServiceImpl implements EmailCaptchaService {
    
    private static final Logger logger = LoggerFactory.getLogger(EmailCaptchaServiceImpl.class);
    
    @Autowired
    private RedisUtil redisUtil;
    
    @Autowired
    private JavaMailSender mailSender;
    
    @Autowired
    private SysUserService sysUserService;
    
    // 发件人邮箱
    private static final String FROM_EMAIL = "3151902195@qq.com";
    
    // 验证码在Redis中的前缀
    private static final String CAPTCHA_PREFIX = "email_captcha:";
    
    // 验证码有效期（分钟）
    private static final long CAPTCHA_EXPIRE_MINUTES = 5;
    
    @Override
    public Map<String, Object> generateCaptcha(String email, String captchaType) {
        try {
            // 检查邮箱格式
            if (!ValidateUtils.isEmail(email)) {
                Map<String, Object> errorResult = new HashMap<>();
                errorResult.put("success", false);
                errorResult.put("message", "邮箱格式不正确");
                return errorResult;
            }
            
            // 验证邮箱是否与用户注册时的邮箱一致（仅对特定类型验证码进行验证）
            if ("forgot-password".equals(captchaType) || "忘记密码".equals(captchaType)) {
                UserVO user = sysUserService.getUserByEmail(email);
                if (user == null) {
                    Map<String, Object> errorResult = new HashMap<>();
                    errorResult.put("success", false);
                    errorResult.put("message", "该邮箱未注册");
                    return errorResult;
                }
                
                if (!email.equals(user.getEmail())) {
                    Map<String, Object> errorResult = new HashMap<>();
                    errorResult.put("success", false);
                    errorResult.put("message", "输入的邮箱与注册时的邮箱不一致");
                    return errorResult;
                }
            }
            
            // 生成6位数字验证码
            String captcha = ValidateUtils.generateSixNumID();
            
            // 存储验证码信息到Redis
            Map<String, Object> captchaInfo = new HashMap<>();
            captchaInfo.put("email", email);
            captchaInfo.put("captcha", captcha);
            captchaInfo.put("captchaType", captchaType);
            captchaInfo.put("createTime", System.currentTimeMillis());
            
            // 存入Redis并设置过期时间
            String captchaInfoJson = JSON.toJSONString(captchaInfo);
            String key = CAPTCHA_PREFIX + email + ":" + captchaType;
            logger.info("生成验证码，Redis键: {}, 验证码: {}, 类型: {}", key, captcha, captchaType);
            redisUtil.set(key, captchaInfoJson, CAPTCHA_EXPIRE_MINUTES, TimeUnit.MINUTES);
            
            // 发送验证码邮件
            boolean emailSent = sendCaptchaEmail(email, captcha);
            
            if (!emailSent) {
                // 发送失败，删除Redis中的验证码
                redisUtil.del(key);
                
                Map<String, Object> errorResult = new HashMap<>();
                errorResult.put("success", false);
                errorResult.put("message", "验证码发送失败");
                return errorResult;
            }
            
            // 构造返回结果
            Map<String, Object> result = new HashMap<>();
            result.put("success", true);
            result.put("message", "验证码已发送至您的邮箱");
            
            return result;
        } catch (Exception e) {
            logger.error("生成邮箱验证码异常", e);
            Map<String, Object> errorResult = new HashMap<>();
            errorResult.put("success", false);
            errorResult.put("message", "生成验证码失败: " + e.getMessage());
            return errorResult;
        }
    }
    
    @Override
    public boolean checkCaptcha(EmailCaptchaDTO emailCaptchaDTO) {
        try {
            String email = emailCaptchaDTO.getEmail();
            String captcha = emailCaptchaDTO.getCaptcha();
            String captchaType = emailCaptchaDTO.getCaptchaType();
            
            logger.info("检查验证码，邮箱: {}, 验证码: {}, 类型: {}", email, captcha, captchaType);
            
            // 检查参数有效性
            if (email == null || email.isEmpty() || captcha == null || captcha.isEmpty()) {
                logger.warn("检查参数不完整，邮箱: {}, 验证码: {}, 类型: {}", email, captcha, captchaType);
                return false;
            }
            
            // 从Redis中获取验证码信息
            String key = CAPTCHA_PREFIX + email + ":" + captchaType;
            logger.info("尝试从Redis获取数据，键: {}", key);
            String captchaInfoJson = (String) redisUtil.get(key);
            logger.info("从Redis获取到的数据: {}", captchaInfoJson);
            
            if (captchaInfoJson == null || captchaInfoJson.isEmpty()) {
                logger.warn("验证码不存在或已过期，键: {}", key);
                return false; // 验证码不存在或已过期
            }
            
            // 解析验证码信息
            Map<String, Object> captchaInfo = JSON.parseObject(captchaInfoJson, Map.class);
            logger.info("解析后的验证码信息: {}", captchaInfo);
            
            // 检查必要字段
            if (!captchaInfo.containsKey("captcha") || !captchaInfo.containsKey("createTime")) {
                logger.warn("验证码信息不完整: {}", captchaInfo);
                return false;
            }
            
            // 获取验证码和创建时间
            String storedCaptcha = (String) captchaInfo.get("captcha");
            long createTime = ((Number) captchaInfo.get("createTime")).longValue();
            
            // 验证是否超时
            long currentTime = System.currentTimeMillis();
            long timeDiff = currentTime - createTime;
            logger.info("当前时间: {}, 创建时间: {}, 时间差: {}ms, 最大允许时间: {}ms", 
                      currentTime, createTime, timeDiff, CAPTCHA_EXPIRE_MINUTES * 60 * 1000);
            
            if (timeDiff > CAPTCHA_EXPIRE_MINUTES * 60 * 1000) {
                redisUtil.del(key); // 清理过期数据
                logger.warn("验证码已过期，键: {}", key);
                return false;
            }
            
            // 验证验证码是否正确
            boolean captchaMatch = captcha.equals(storedCaptcha);
            logger.info("输入验证码: {}, 存储验证码: {}, 是否匹配: {}", captcha, storedCaptcha, captchaMatch);
            
            return captchaMatch;
        } catch (Exception e) {
            logger.error("检查邮箱验证码异常", e);
            return false;
        }
    }
    
    @Override
    public boolean verifyCaptcha(EmailCaptchaDTO emailCaptchaDTO) {
        try {
            String email = emailCaptchaDTO.getEmail();
            String captcha = emailCaptchaDTO.getCaptcha();
            String captchaType = emailCaptchaDTO.getCaptchaType();
            
            // 先检查验证码
            boolean isValid = checkCaptcha(emailCaptchaDTO);
            if (!isValid) {
                return false;
            }
            
            // 验证成功后删除验证码，防止重复使用
            String key = CAPTCHA_PREFIX + email + ":" + captchaType;
            redisUtil.del(key);
            logger.info("验证码验证成功，已删除验证码: {}", key);
            return true;
        } catch (Exception e) {
            logger.error("验证邮箱验证码异常", e);
            return false;
        }
    }
    
    @Override
    public boolean sendCaptchaEmail(String email, String captcha) {
        try {
            SimpleMailMessage message = new SimpleMailMessage();
            message.setFrom(FROM_EMAIL);
            message.setTo(email);
            message.setSubject("学生成长记录系统 - 邮箱验证码");
            message.setText("您的验证码是: " + captcha + "，有效期为5分钟。");
            
            mailSender.send(message);
            logger.info("发送验证码邮件到: {}，验证码: {}", email, captcha);
            return true;
        } catch (Exception e) {
            logger.error("发送验证码邮件失败", e);
            return false;
        }
    }
}